/**
 * Copyright (C) 2010 KingCore Science & Technology CO,.LTD. All rights reserved.
 * XNS PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/**
 * Copyright (C) 2002-2010 WUZEWEN. All rights reserved.
 * WUZEWEN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 * This software is the confidential and proprietary information of
 * WuZeven, Personal. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with WuZeven.
 */

package com.kingcore.director.note.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Event;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Observable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JColorChooser;
import javax.swing.JEditorPane;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyledEditorKit;
import javax.swing.undo.UndoManager;

import org.apache.log4j.Logger;

import com.kingcore.director.base.ui.DirectorPanel;
import com.kingcore.director.core.ui.FontChooser;
import com.kingcore.director.core.util.DirectorComponentUtils;
import com.kingcore.director.core.util.Formatter;
import com.kingcore.director.main.MainFrame;
import com.kingcore.director.note.dao.NotePaperDao;
import com.kingcore.director.note.dao.impl.NotePaperDaoImpl;

/**
 * <p>java class file describe</p>
 * @author Zeven on 2010-8-30
 * @version	1.0
 * @see		Object#equals(java.lang.Object)
 * @since	JDK5
 */

public class NotePaperMainPanel extends DirectorPanel implements MouseListener, KeyListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	//log object
	private final static Logger log = Logger.getLogger(NotePaperMainPanel.class);

	private static int AutoSave_Interval = 3; //秒数
	public NotePaperMainPanel(MainFrame baseFrame) {
		super(baseFrame); 
		initializeInterface();
		
		this.update(null, null);
		constructAfter();
	}
 
	private void initializeInterface(){
        this.setLayout(new BorderLayout()); 

		this.add( getToolBar(true), BorderLayout.NORTH);
        this.add( getScrollPane(), BorderLayout.CENTER );
		this.add( getStatusBar(true), BorderLayout.SOUTH);
         
		this.update(null, null);	
		this.getContentTextPane().setCaretPosition(0);
//		this.getContentTextPane().setSelectionStart(0);
//		this.getContentTextPane().setSelectionEnd(0);
		
		try {
			fetchData();
		} catch (SQLException e) { 
			e.printStackTrace();
		}
		
		//填充数据之后会修改状态栏内容，所以设置监听放在取数后面
		getContentTextPane().getDocument().addDocumentListener(new DocumentListener(){
			@Override
			public void insertUpdate(DocumentEvent e) {
				log.debug("insertUpdate");
				doSaveNote();
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				log.debug("removeUpdate");
				doSaveNote();
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				log.debug("changedUpdate");
				doSaveNote();
			}
			
		});
		
		refreshView(); 
	}

	@Override
	public void refreshView() { 
		super.refreshView();
		
		this.getContentTextPane().requestFocusInWindow();
	}

	@Override
	public void setToolBarVisible(boolean isToolBarShow) {
		if (isToolBarShow) {
			this.add( getToolBar(), BorderLayout.NORTH);
		}else{
			this.remove( getToolBar() );
		}
	} 
	
	private JScrollPane scrollPane = null;
	/**
	 * This method initializes leftScrollPane
	 *
	 * @return javax.swing.JScrollPane
	 */
	private JScrollPane getScrollPane() {
		if (scrollPane == null) {
	        // 设置文本区的滚动条
	        int v = ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
	        int h = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
	        scrollPane = new JScrollPane( v, h ); //, v, h
	        scrollPane.setViewportView( getContentTextPane() );
	        scrollPane.getVerticalScrollBar().setValue(0);
		}
		return scrollPane;
	}
	
	//定时执行服务器
	ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
	ScheduledFuture<?> saveNoteFuture = null;
	
	//增加10秒之后执行的任务，如果中间修改了，往后延时间隔秒数相同
	protected void doSaveNote() {
		if(saveNoteFuture!=null){
			if(saveNoteFuture.isDone()==false){
				saveNoteFuture.cancel(false); //终止上一次保存的任务，但不强制终止
			}
			currentStatusInfor = this.statusBar_ready;
			setStatus( StatusBar_Index_One, currentStatusInfor);
		}
		//add new schedule
		saveNoteFuture = scheduledExecutorService.schedule(new Runnable() {
			public void run() {
				saveImmediately();
			}
		}, AutoSave_Interval, TimeUnit.SECONDS);    //n秒后自动保存		
	}
	
	private JTextPane contentTextPane = null;
	private JTextPane getContentTextPane(){
		if (contentTextPane==null) {
			contentTextPane = new JTextPane();
			contentTextPane.addMouseListener( this );
			contentTextPane.setToolTipText("系统自动保存修改的内容");
			contentTextPane.setBackground(new Color(205,232,207));
			
			contentTextPane.addKeyListener(this);
			contentTextPane.getDocument().addUndoableEditListener( getUndoManager()  );
		}
		return contentTextPane;
	}

	/**
	 * <p>java method describe</p>
	 * @author Zeven on 2010-8-30
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean fetchData() throws SQLException {

		NotePaperDao dcd = new NotePaperDaoImpl();
		Object obj = dcd.queryNotePaper(); //   ComponentUtil.LookAndFeel_Current ;
		if (obj!=null) {
			this.getContentTextPane().setStyledDocument((StyledDocument) obj); //
			this.getContentTextPane().getDocument().addUndoableEditListener(getUndoManager());
		}
	    this.getContentTextPane().setCaretPosition(0);
	    this.scrollPane.getVerticalScrollBar().setValue(0);
	   	return true;
	}

	@Override
	public boolean saveData()  throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

    // 设置文本区选择文本的样式
    public void setCharacterAttributes(JEditorPane editor, AttributeSet attr,
                    boolean replace) {
            // 取得选择文本的起始位置和结束位置
            int p0 = editor.getSelectionStart();
            int p1 = editor.getSelectionEnd();

            // 如果选中文本，设置选中文本的样式
            if (p0 != p1) {
                    StyledDocument doc = (StyledDocument) getContentTextPane().getDocument();

                    // 将所选文本设置为新的样式，replace为false表示不覆盖原有的样式
                    doc.setCharacterAttributes(p0, p1 - p0, attr, replace);
            }
            // 如果没有选中文本，设置当前光标处默认的文本样式
            else {
                    StyledEditorKit k = (StyledEditorKit) getContentTextPane().getEditorKit();
                    MutableAttributeSet inputAttributes = k.getInputAttributes();
                    if (replace) {
                            inputAttributes.removeAttributes(inputAttributes);
                    }
                    inputAttributes.addAttributes(attr);
            }
    }
    
	public void actionPerformed(ActionEvent e) {
		super.actionPerformed(e);
		
		Object obj = e.getSource() ;
		// 处理字体设置
        if (obj == fontItem) {
                // 设置字体选择对话框
                FontChooser fc = new FontChooser();
                Font font = fc.getFont();
                if (font != null) {
                        // 调用setCharacterAttributes函数设置文本区选择文本的字体
                        MutableAttributeSet attr = new SimpleAttributeSet();
                        StyleConstants.setFontFamily(attr, font.getFamily());
                        StyleConstants.setBold(attr, font.isBold());
                        StyleConstants.setItalic(attr, font.isItalic());
                        StyleConstants.setFontSize(attr, font.getSize());
                        setCharacterAttributes( getContentTextPane(), attr, false);
                }
        }
        // 处理下划线设置
        else if (obj == underLineItem) {
                // 调用setCharacterAttributes函数设置文本区选择文本的下划线
                MutableAttributeSet attr = new SimpleAttributeSet();
                StyleConstants.setUnderline(attr, underLineItem.isSelected());
                setCharacterAttributes(getContentTextPane(), attr, false);

        }
        // 处理前景色设置
        else if (obj == foreColor) {
                // 设置颜色选择对话框
                Color color = JColorChooser.showDialog(this, "前景色", getContentTextPane()
                                .getForeground());
                if (color != null) {
                        // 调用setCharacterAttributes函数设置文本区选择文本的前景色
                        MutableAttributeSet attr = new SimpleAttributeSet();
                        StyleConstants.setForeground(attr, color);
                        setCharacterAttributes(getContentTextPane(), attr, false);
                }
        }
        // 处理背景色设置
        else if (obj == backColor) {
            // 设置颜色选择对话框
            Color color = JColorChooser.showDialog(this, "背景色", getContentTextPane()
                            .getForeground());
            if (color != null) {
                    // 调用setCharacterAttributes函数设置文本区选择文本的背景色
                    MutableAttributeSet attr = new SimpleAttributeSet();
                    StyleConstants.setBackground(attr, color);
                    setCharacterAttributes(getContentTextPane(), attr, false);
            }
	    } //添加新内容提醒
	      else if (obj == selected2Awoke) {
				this.mainFrame.getReminderMainPanel().executeAddNewContentAwoke( this.getContentTextPane().getSelectedText() );
	    
	      } //添加新内容提醒
	      else if (obj == insertDate) {
	    	  insertDate();
	    	  
	    }else if (obj == undo) {
	    	editUndo();
	    	
	    }else if (obj == redo) {
	    	editRedo();
	    	
	    }else if (obj == save) {
	    	saveImmediately();
	    }
	}

	/**
	 * 除了自动保存外，提立即保存功能。
	 */
	private void saveImmediately() {
		try {
			NotePaperDao npd = new NotePaperDaoImpl();
			//String t_content = getContentTextPane().getStyledDocument().getText(0, getContentTextPane().getStyledDocument().getLength());
			//t_content = getContentTextPane().getText();
			//System.out.println(t_content); 
			getContentTextPane().getDocument().removeUndoableEditListener(getUndoManager());		
			npd.updateNotePaper( getContentTextPane().getStyledDocument() );
			//getContentTextPane().getInputAttributes().
			currentStatusInfor = statusBar_saveSuccess ;
			setStatus( StatusBar_Index_One, currentStatusInfor);
		
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			//保存前要移除监听器，因为这个对象没有序列化，不能序列化
			getContentTextPane().getDocument().addUndoableEditListener(getUndoManager());
		}
	}

	protected void editUndo(){
	   if (undoManager.canUndo()){
		   undoManager.undo();
		}
	}
	
	protected void editRedo(){
	   if (undoManager.canRedo()){
		   undoManager.redo();
		}
	}
	
	private void insertDate() {
		try {
			//this.getContentTextPane().getDocument().insertString(0, "2011", null);
			this.getContentTextPane().replaceSelection(Formatter.format(Calendar.getInstance().getTime(), "yyyy-MM-dd"));
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	@Override
	public void update(Observable o, Object arg) {
		super.update(o, arg);
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		Object obj = e.getSource() ;
		if(obj==getContentTextPane()){
			if( e.getButton() == MouseEvent.BUTTON3 ) {	//显示弹出菜单
				
				//System.out.println (getTable().getX()+e.getX());
				//getPopupMenuForTable().locate( getTable().getX()+e.getX(), getTable().getY()+e.getY() );
				//getPopupMenuForTable().setVisible( true );
				getPopupMenuForTextPane().setSelected(null);
				getPopupMenuForTextPane().show( e.getComponent(), e.getX(), e.getY() );
				
			}
		}
	}


    // 菜单
    JMenuItem undo = null;
    JMenuItem redo = null;
    JMenuItem save = null;
    JMenuItem fontItem = null;
    JCheckBoxMenuItem underLineItem = null;
    JMenuItem foreColor = null;
    JMenuItem backColor = null;
    JMenuItem selected2Awoke = null;
    JMenuItem insertDate = null;
	private JPopupMenu popupMenuForTable =null;
	/**
	 * Table的弹出式菜单
	 */
	private JPopupMenu getPopupMenuForTextPane(){
		
		if(popupMenuForTable == null){
			popupMenuForTable = new JPopupMenu();

	        // 菜单
	        undo = new JMenuItem("撤销");
	        undo.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK) ); //Write informal essay
	        redo = new JMenuItem("重做");
	        redo.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK) ); //Write informal essay
	        save = new JMenuItem("保存");
	        save.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK) ); //Write informal essay
	        fontItem = new JMenuItem("字体");
	        underLineItem = new JCheckBoxMenuItem("下划线");
	        foreColor = new JMenuItem("前景色");
	        backColor = new JMenuItem("背景色");
	        selected2Awoke = new JMenuItem("添加选中内容到提醒");
	        insertDate = new JMenuItem("插入当前日期");
	        insertDate.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_D, Event.CTRL_MASK) ); //Write informal essay

	        // 添加事件监听器
	        undo.addActionListener(this);
	        redo.addActionListener(this);
	        save.addActionListener(this);
            fontItem.addActionListener(this);
            underLineItem.addActionListener(this);
            foreColor.addActionListener(this);
            backColor.addActionListener(this);
            selected2Awoke.addActionListener(this);
            insertDate.addActionListener(this);
            
            // 添加菜单
	        popupMenuForTable.add(undo);
	        popupMenuForTable.add(redo);
	        popupMenuForTable.add(save);
	        popupMenuForTable.addSeparator();
	        popupMenuForTable.add(fontItem);
	        popupMenuForTable.add(underLineItem);
	        popupMenuForTable.add(foreColor);
	        popupMenuForTable.add(backColor);
	        popupMenuForTable.addSeparator();
	        popupMenuForTable.add(selected2Awoke);
	        popupMenuForTable.add(insertDate);
		}
		return popupMenuForTable;		
	}
	
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyPressed(KeyEvent e) {
		Object obj = e.getSource();
		int keyCode = e.getKeyCode();
		
		if ( obj==this.getContentTextPane() ){
			if(keyCode==KeyEvent.VK_D && DirectorComponentUtils.isControlDownOnly(e)){
				insertDate();
				e.consume();    //本窗口优先处理，事件终止。
			}else if(keyCode==KeyEvent.VK_Z && DirectorComponentUtils.isControlDownOnly(e)){
				editUndo();
				e.consume(); 
			}else if(keyCode==KeyEvent.VK_Y && DirectorComponentUtils.isControlDownOnly(e)){
				editRedo();
				e.consume();  
			}else if(keyCode==KeyEvent.VK_S && DirectorComponentUtils.isControlDownOnly(e)){
				saveImmediately();
				e.consume();  
			}
	    }
	    
	}
	
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	private UndoManager undoManager = null; 
	private UndoManager getUndoManager(){
		if (undoManager==null) {
			undoManager = new UndoManager(); // {
//				  private static final long serialVersionUID = -5960092671497318496L;
//				  public void undoableEditHappened(UndoableEditEvent e) {
//					  this.addEdit(e.getEdit());
//				  }
//				 };
		}
		return undoManager;
	}
	 
}
